package com.alogic.cert.bc.builder;

import com.alogic.cert.bc.CertificateStoreImpl;
import com.alogic.cert.bc.GeneralNameTools;
import com.alogic.xscript.AbstractLogiclet;
import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.anysoft.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.List;

/**
 * 增加SubjectAlternativeName
 *
 * @since 1.6.13.40 [20210306 duanyy] <br>
 */
public class AddSAN extends AbstractLogiclet {
    protected String pid = CertificateStoreImpl.XSCRIPT_OBJECT_ID;
    protected String $critical = "true";
    protected List<Pair<String,String>> names = new ArrayList<Pair<String,String>>();
    protected String delimiter = ",";

    public AddSAN(String tag, Logiclet p) {
        super(tag, p);
    }

    @Override
    public void configure(Properties p){
        super.configure(p);
        pid = PropertiesConstants.getString(p,"pid",pid,true);
        delimiter = PropertiesConstants.getString(p,"delimiter",delimiter,true);
    }

    @Override
    public void configure(Element e, Properties p) {
        Properties props = new XmlElementProperties(e,p);
        configure(props);

        NodeList nodeList = XmlTools.getNodeListByPath(e,"san");
        for (int i = 0 ; i < nodeList.getLength() ; i ++){
            Node node = nodeList.item(i);
            if (Node.ELEMENT_NODE != node.getNodeType()){
                continue;
            }
            Element elem = (Element)node;
            String tag = elem.getAttribute("tag");
            String name = elem.getAttribute("name");
            if (StringUtils.isNotEmpty(tag) && StringUtils.isNotEmpty(name)){
                names.add(new Pair.Default<String,String>(tag,name));
            }
        }
    }

    @Override
    protected void onExecute(XsObject root, XsObject current, final LogicletContext ctx, final ExecuteWatcher watcher){
        X509v3CertificateBuilder builder  = ctx.getObject(pid);
        if (builder != null){
            try {
                ArrayList<GeneralName> namesList = new ArrayList<GeneralName>();
                for (Pair<String,String> pair:names){
                    String tag = PropertiesConstants.transform(ctx,pair.key(),"");
                    String name = PropertiesConstants.transform(ctx,pair.value(),"");
                    if (StringUtils.isNotEmpty(tag)&&StringUtils.isNotEmpty(name)){
                        Integer tagValue = GeneralNameTools.getByName(tag);
                        if (tagValue != null){
                            String names[] = name.split(delimiter);
                            for (String item:names) {
                                if (StringUtils.isNotEmpty(item)) {
                                    namesList.add(new GeneralName(tagValue, item));
                                }
                            }
                        }
                    }
                }
                if (namesList.size() > 0) {
                    GeneralNames subjectAltNames = new GeneralNames(namesList.toArray(new GeneralName[namesList.size()]));
                    builder.addExtension(Extension.subjectAlternativeName, PropertiesConstants.transform(ctx, $critical, true), subjectAltNames);
                }
            }catch (Exception ex){
                log(ExceptionUtils.getStackTrace(ex));
            }
        }
    }
}
